package com.didispace.hystrix;

import com.didispace.web.User;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.web.client.RestTemplate;
import rx.Observable;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class UserCommand extends HystrixCommand<User> {

    private RestTemplate restTemplate;
    private Long id;

    public UserCommand(Setter setter, RestTemplate restTemplate, Long id){
        super(setter);
        this.restTemplate = restTemplate;
        this.id = id;
    }

    /**
     * 注意本地main方法启动，url请用http://localhost:8081/user
     * 通过controller请求启动需要改为服务调用地址：http://eureka-service/user
     */
    @Override
    protected User run() {
        // return restTemplate.getForObject("http://localhost:8081/users/{1}", User.class, id); 书上的运行不正确  p152
        //本地请求
       return restTemplate.getForObject("http://localhost:8081/users", User.class);
        //连注册中心请求
        // return restTemplate.getForObject("http://USER-SERVICE/users", User.class);
    }

    // 定义服务降级  p154
    @Override
    protected User getFallback() {
        return new User();
    }


    /** SpringCloud （七）自定义HystrixCommand
     * https://blog.csdn.net/u012586326/article/details/112343696
     * 此方法为《spirngcloud微服务实战》中的学习部分，仅用于在此项目启动的之后调用本地服务，但是不能没有走注册中心。
     * 书中为我们留下了这个坑，详情请直接翻阅151页。
     * 问题解决请参考：https://blog.csdn.net/lvyuan1234/article/details/76550706
     * 本人在书中基础上已经完成调用注册中心服务的功能，见RibbonService类中具体实现
     */
    // public static void main(String[] args) {
    //     //初始化请求上下文，这一行只在main方法中维持之前代码的可用
    //     HystrixRequestContext.initializeContext();
    //
    //     //同步请求（同步执行）
    //     // User u = new UserCommand(restTemplate, 1L).execute();  书上的运行不正确  p152
    //     User userSync=new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(
    //             HystrixCommandGroupKey.Factory.asKey("")).andCommandPropertiesDefaults(
    //             HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)),
    //             new RestTemplate(),0L).execute();
    //     System.out.println("------------------This is sync request's response:"+userSync);
    //
    //     //异步请求（异步执行）
    //     // Future<User> userFuture = new UserCommand(restTemplate, 1L).queue();  书上的运行不正确  p152
    //     Future<User> userFuture = new UserCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(
    //             HystrixCommandGroupKey.Factory.asKey("")).andCommandPropertiesDefaults(
    //             HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)),
    //             new RestTemplate(),0L).queue();
    //
    //     User userAsync = null;
    //
    //     try {
    //         userAsync = userFuture.get();
    //     } catch (InterruptedException e) {
    //         e.printStackTrace();
    //     } catch (ExecutionException e) {
    //         e.printStackTrace();
    //     }
    //     System.out.println("------------------This is async request's response:"+userAsync);
    //
    //     System.out.println("除了传统的同步执行与异步执行之外，我们还可以将 HystrixComrnand 通过 Observable 来实现响应式执行方式。");
    //     System.out.println("通过调用 observe() 和 toObservable() 方法可以返回 Observable 对象");  // p152
    //     // Observable<String> ho = new UserCommand(restTemplate, lL) .observe();
    //     // Observable<String> co = new UserCommand(restTemplate, lL) .toObservable();
    //
    //     // 前者返回的是一个 Hot Observable，该命令会在 observe() 调用的时候立即执行，当 Observable 每次被订阅的时候会重放它的行为
    //     // 而后者返回的是一个 Cold Observable，toObservable ()执行之后，命令不会被立即执行，只有当所有订阅者都订阅它之后才会执行
    //     Observable<User> ho = new UserCommand(Setter.withGroupKey(
    //             HystrixCommandGroupKey.Factory.asKey("")).andCommandPropertiesDefaults(
    //             HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)),
    //             new RestTemplate(),0L).observe();
    //     System.out.println(ho);
    //     Observable<User> co = new UserCommand(Setter.withGroupKey(
    //             HystrixCommandGroupKey.Factory.asKey("")).andCommandPropertiesDefaults(
    //             HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)),
    //             new RestTemplate(),0L).toObservable();
    //     System.out.println(co);
    // }
}

// Unable to find a single main class from the following candidates
// https://blog.csdn.net/YFSREAD/article/details/103892810
// Unable to find a single main class from the following candidates [com.didispace.ConsumerApplication, com.didispace.hystrix.UserCommand]
// 错误原因：当前项目下无法找到单个main方法（因为当前项目有两个main方法（有时可能有多个）此些main方法会列在[]括号中）
// 解决方式：把非启动类中的那些main方法注释掉，保证只有一个main方法。

// 15:33:42.716 [hystrix--1] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8081/users"
//         15:33:42.761 [hystrix--1] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json]
// 15:33:42.793 [hystrix--1] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:8081/users" resulted in 200 (OK)
// 15:33:42.793 [hystrix--1] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.didispace.web.User] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7e366b69]
// ------------------This is sync request's response:name=zhaiyongchao, age=17
// 15:33:42.818 [hystrix--2] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8081/users"
// 15:33:42.819 [hystrix--2] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json]
// 15:33:42.824 [hystrix--2] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:8081/users" resulted in 200 (OK)
// 15:33:42.824 [hystrix--2] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.didispace.web.User] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2e2a8b57]
// ------------------This is async request's response:name=zhaiyongchao, age=17
// 除了传统的同步执行与异步执行之外，我们还可以将 HystrixComrnand 通过 Observable 来实现响应式执行方式。
//         通过调用 observe() 和 toObservable() 方法可以返回 Observable 对象
//         rx.Observable@19e4fcac
//         16:27:34.850 [hystrix--3] DEBUG org.springframework.web.client.RestTemplate - Created GET request for "http://localhost:8081/users"
//         16:27:34.851 [hystrix--3] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json]
// 16:27:34.855 [hystrix--3] DEBUG org.springframework.web.client.RestTemplate - GET request for "http://localhost:8081/users" resulted in 200 (OK)
// 16:27:34.856 [hystrix--3] DEBUG org.springframework.web.client.RestTemplate - Reading [class com.didispace.web.User] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@48230bb3]
// rx.Observable@72437d8d
